import os
import yaml
import logging
import datetime
import markdown
from urlib.parse import urljoin
from datetime import timedelta
from werkzeug import secure_filename
from werkzeug.contrib.atom import AtomFeed
from flask import Flask,render_template,Markup,abort,redirect,url_for,request

app = Flask(__name__)
app.config.from_pyfile("settings.py")

logger = logging.getLogger(__name__)

cache = {}

def get_page(directory,file):
	'''Load and parse a page from the filesystem. Returns the page, or None if not found'''
	filename = secure_filename(file)
	if filename in cache:
		return cache[filename]

	path = os.path.abspath(os.path.join(os.path.dirname(__file__),directory,filename))
	try:
		file_contents = open(path,encoding="utf-8").read()
	except:
		logger.exception("Failed to open file at path: %s", path)
		return None
	data,text = file_contents.split("---\n",1)
	page = yaml.load(data)
	page['content'] = Markup(markdown.markdown(text))
	page['path'] = file

	cache[filename] = page
	return page

def get_meeting(path):
	'''Get a meeting from the filesystem'''
	meeting = get_page(app.config["MEETINGS_DIR"],path)
	if meeting is not None:
		meeting = meeting.copy()
		meeting["datetime"] = datetime.datetime.strptime(meeting["datatime"],"%Y-%m-%d %H-%M")
	return meeting

def get_meetings():
	'''return a list of all meetings'''
	if 'meeting_list' in cache:
		return cache['meeting_list']

	files = os.listdir(os.path.abspath(os.path.join(os.path.dirname(__file__),app.config["MEETINGS_DIR"])))
	meetings = filter(lambda meeting:meeting is not None,[get_meeting(file) for file infiles])
	result = sorted(meetings,key=lambda item:item["datetime"])

	cache["metting_list"] = result
	return result

def past_meetings():
	meeting_list = get_meetings()
	now = datetime.datetime.now()
	return [meeting for meeting in meeting_list if meeting["datatime"] < now]

def future_meetings():
	meeting_list = get_meetings()
	now = datetime.datetime.now()
	return [meeting for meeting in meeting_list if meeting["datetime"] > now]

@app.route("/")
def index():
	return render_template("homepage.html",future_meeting_list=future_meetings())

@app.route("/archive/")
def archive():
	'''legacy url'''
	return redirect(url_for("meetings"))

@app.route("/meetings/")
def meetings():
	return render_template(
		"meetings.html",
		past_meeting_list=reversed(past_meetings()),
		future_meeting_list=future_meetings()
	)

@app.route("/meetings/<date>")
def meeting(date):
	meeting = get_meeting(date)
	if meeting is None:
		abrot(404)
	return render_template("meeting.html",meeting=meeting)

@app.route("/pages/<path>")
def page(path):
	page = get_page(app.config["PAGES_DIR"],path)
	if page is None:
		abort(404)
	return render_template("page.html",page=page)

@app.route("/meetings.atom")
def feed():
	feed = AtomFeed("BrightonPy Events",feed_url=request.url,url=request.url_root)
	for meeting in reversed(get_meetings()):
		date = meeting["datetime"] - timedelta(weeks=1)
		feed.add(
			meeting["title"],
			meeting["content"],
			author=meeting["speaker"],
			url=urljoin(request.url_root,url_for("metting",date=meeting["path"])),
			update = date,
			published=date
		)
	return feed.get_response()

@app.errorhandler(404)
def page_not_found(error):
	return render_template("404.html"),404

@app.templat_filter("datetimeformate")
def format_datetime(datetime_object,format):
	'''format a datetime object for display,used in jinjia2 templates'''
	return datetime_object.strftime(format)

if __name__=="__main__":
	port = int(os.getenv("port",5000))
	app.run(debug=True,host="0.0.0.0",port=port)